/*!
    Copyright (c) 2025, Aprilhome.
    brief:     AHFS文件系统
    说明：支持异常断电保护、支持磨损均衡
    1. 需要支持flash读写，用于断电恢复保存元数据和当前索引数据
    2. 需要支持存储器操作，disk_initlize()，disk_read()，disk_write()
    3. 需要支持实时时钟，get_fattime()
    4. 需要支持串口输出，put_pm()
    5. 支持多索引，每个索引包含一个时间戳和数据长度，索引编号从0开始，并且不会清零
    6. 支持写数据，支持整扇区和非整扇区，建议写入的时候写整扇区
    7. 支持读数据，到串口
    8. 支持格式化，格式化后会清空所有数据
    9. 支持读文件列表，到串口
    10. 支持计算存储空间

    Change Logs:
    Date           Author       Notes
    2025/04/30     Aprilhome    first version
*/
/* Include files */
#include "ahfs.h"
#include "ahfs_config.h"
#include "diskio.h"

/* Local pre-processor symbols/macros ('#define') */
#define MAGIC_NUMBER (0x41484653) /* AHFS */

/* Local type definitions ('typedef') */
/* Local function prototypes ('static') */
/* Local variable definitions ('static') */
static uint16_t g_write_storage_counts = 0; // 写数据的次数，达到一定次数后才一次性写入到存储器中

/* Global variable definitions (declared in header file with 'extern') */

/*!
    @brief:     根据索引编号，计算索引所在的扇区和在扇区内的偏移
    @param[in]: fs 文件系统结构体指针
    @param[in]: index_id 索引编号
    @param[out]:sector 索引所在的扇区
    @param[out]:pos 索引在扇区中的偏移(单位:索引)
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
*/
static int8_t get_ring_index_location(ahfs_t *fs, uint32_t index_id, uint32_t *sector, uint16_t *pos)
{
    if (fs == NULL || sector == NULL || pos == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }
    /* 计算相对于逻辑起始索引扇区的偏移量 */
    uint32_t sector_offset = index_id / fs->indexes_per_sector;

    /* 计算相对于物理起始索引扇区的偏移量 */
    uint32_t physical_offset = fs->metadata.logical_index_start_sector -
                               fs->metadata.physical_index_start_sector +
                               sector_offset;

    /* 计算环形偏移量 */
    uint32_t ring_offset = physical_offset % fs->total_index_sectors;

    /* 计算索引所在的物理扇区 */
    *sector = fs->metadata.physical_index_start_sector + ring_offset;

    /* 计算索引在扇区内的偏移 */
    *pos = index_id % fs->indexes_per_sector;

    return AHFS_RES_OK;
}

/*!
    @brief:     计算相对于逻辑起始数据扇区的偏移后的数据扇区
    @param[in]: fs 文件系统结构体指针
    @param[in]: offset_sector 相对于逻辑起始数据扇区的偏移量(单位:扇区)
    @param[out]:sector 数据扇区的物理扇区
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
*/
static int8_t get_ring_data_sector(ahfs_t *fs, int32_t offset_sector, uint32_t *sector)
{
    if ((fs == NULL) || (sector == NULL))
    {
        return AHFS_RES_ERR_PTR;
    }
    if (offset_sector < 0)
    {
        offset_sector += fs->total_data_sectors;
    }
    /* 计算相对于物理起始数据扇区的偏移量 */
    uint32_t physical_offset = fs->metadata.logical_data_start_sector -
                               fs->metadata.physical_data_start_sector +
                               offset_sector;

    /* 计算环形偏移量 */
    uint32_t ring_offset = physical_offset % fs->total_data_sectors;

    /* 计算索引所在的物理扇区 */
    *sector = fs->metadata.physical_data_start_sector + ring_offset;
    return AHFS_RES_OK;
}

/*!
    @brief:     将元数据和当前索引写入存储器
    @param[in]: fs 文件系统结构体指针
    @param[out]:none
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
*/
static int8_t write_metadata_index_to_storage(ahfs_t *fs)
{
    if (fs == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }
    else
    {
        /* 1 写元数据到存储器 */
        memset(fs->buf, 0, AHFS_SECTOR_SIZE);
        memcpy(fs->buf, (uint8_t *)(&(fs->metadata)), sizeof(struct ahfs_metadata));
        if (disk_write(0, fs->buf, fs->metadata.physical_metadata_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }

        /* 2 写索引到存储器 */
        uint32_t index_sector = 0;
        uint16_t index_pos = 0;
        if (get_ring_index_location(fs, fs->metadata.current_index_id, &index_sector, &index_pos) != AHFS_RES_OK)
        {
            return AHFS_RES_ERR_PTR;
        }
        if (disk_read(0, fs->buf, index_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }
        memcpy((struct ahfs_index *)fs->buf + index_pos,
               &(fs->current_index),
               sizeof(struct ahfs_index));
        if (disk_write(0, fs->buf, index_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }
        return AHFS_RES_OK;
    }
}

/*!
    @brief:     从存储器中读取元数据和当前索引
    @param[in]: fs 文件系统结构体指针
    @param[out]:fs->metadata 元数据
                fs->current_index 当前索引
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
*/
static int8_t read_metadata_index_from_storage(ahfs_t *fs)
{
    if (fs == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }
    else
    {
        /* 1 读取元数据 */
        if (disk_read(0, fs->buf, fs->metadata.physical_metadata_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }
        memcpy(&(fs->metadata), fs->buf, sizeof(struct ahfs_metadata));

        /* 2 读取索引 */
        uint32_t index_sector = 0;
        uint16_t index_pos = 0;
        if (get_ring_index_location(fs, fs->metadata.current_index_id, &index_sector, &index_pos) != AHFS_RES_OK)
        {
            return AHFS_RES_ERR_PTR;
        }

        if (disk_read(0, fs->buf, index_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }
        memcpy(&(fs->current_index),
               (struct ahfs_index *)(fs->buf) + index_pos,
               sizeof(struct ahfs_index));

        return AHFS_RES_OK;
    }
}

/*!
    @brief:     初始化存储器
    @param[in]: none
    @param[out]:none
    @retval:    DSTATUS
                AHFS_RES_OK = 0,		 0: Successful 
                RES_ERROR,		 1: R/W Error 
                RES_WRPRT,		 2: Write Protected 
                RES_NOTRDY,		 3: Not Ready 
                RES_PARERR		 4: Invalid Parameter                
*/
int8_t ahfs_init_storage(void)
{
    int8_t ret = AHFS_RES_OK;

    /* 1 初始化存储器 */
    ret = disk_initialize(0);

    return ret;    
}

/*!
    @brief:     文件系统初始化
                优先从flash读取元数据和当前索引
                    如果读取成功,则同步到存储器。并计算预计算参数
                    如果读取失败,则从存储器中读取元数据和索引,
                        如果读取成功,则计算预计算参数
                        如果读取失败,则返回错误信息,提示需要格式化文件系统
    @param[in]: fs 文件系统结构体指针
    @param[out]:fs 文件系统结构体指针
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
                AHFS_RES_ERR_FS 文件系统错误
*/
int8_t ahfs_init_fs(ahfs_t *fs)
{
    if ((fs == NULL) ||
        (fs->ahfs_put_serial == NULL) || (fs->ahfs_calculate_CRC16 == NULL) || 
        (fs->ahfs_read_metadata_index_from_flash == NULL) || 
        (fs->ahfs_write_metadata_index_to_flash == NULL) ||
        (fs->ahfs_generate_file_info_format == NULL))
    {
        return AHFS_RES_ERR_PTR;
    }
    else
    {
        /* 1 从flash读取元数据和索引 */
        if (fs->ahfs_read_metadata_index_from_flash(&(fs->metadata), &(fs->current_index)) == AHFS_RES_OK)
        {
            /* 2 检查元数据和索引是否有效 */
            uint16_t crc16 = 0;
            crc16 = fs->ahfs_calculate_CRC16((uint8_t *)&(fs->metadata), sizeof(struct ahfs_metadata) - 2);
            /* 3 元数据和索引有效,将元数据和索引写入存储器
                 用于支持异常断电后恢复,因为异常断电可能导致没有写入存储器,但是写入了flash,从flash中强制同步至存储器
            */
            if ((fs->metadata.magic_number == MAGIC_NUMBER) && (fs->metadata.crc16 == crc16))
            {
                /* 3 元数据和索引有效,计算预计算参数,将元数据和索引写入存储器,返回成功 */
                fs->indexes_per_sector = fs->metadata.sector_size / sizeof(struct ahfs_index);
                fs->total_index_sectors = (fs->metadata.max_indexes + fs->indexes_per_sector - 1) / fs->indexes_per_sector; // 索引区扇区总数,利用向上取整技巧
                fs->total_data_sectors = fs->metadata.total_sectors - fs->total_index_sectors - 1;
                if (write_metadata_index_to_storage(fs) == AHFS_RES_OK)
                {
                    return AHFS_RES_OK;
                }
                else
                {
                    return AHFS_RES_ERR_RW;
                }
            }
            else
            {
                /* 4 元数据和索引无效,从存储器读元数据和索引,看是否存在且有效
                     用于换sd卡到其他电路板上回放数据,操作步骤如下:
                     1. 断电状态,电路板拔掉旧sd卡
                     2. 电路板上电,发送指令反初始化电路板flash为无文件系统
                     3. 电路板断电
                     4. 电路板插上新sd卡
                     5. 电路板上电,自动读取新卡的元数据和索引,并初始化
                */
                if (read_metadata_index_from_storage(fs) == AHFS_RES_OK)
                {
                    /* 5 检查元数据和索引是否有效 */
                    crc16 = fs->ahfs_calculate_CRC16((uint8_t *)&(fs->metadata), sizeof(struct ahfs_metadata) - 2);
                    /* 6 元数据和索引有效,计算预计算参数,返回成功 */
                    if ((fs->metadata.magic_number == MAGIC_NUMBER) && (fs->metadata.crc16 == crc16))
                    {
                        fs->indexes_per_sector = fs->metadata.sector_size / sizeof(struct ahfs_index);
                        fs->total_index_sectors = (fs->metadata.max_indexes + fs->indexes_per_sector - 1) / fs->indexes_per_sector; // 索引区扇区总数,利用向上取整技巧
                        fs->total_data_sectors = fs->metadata.total_sectors - fs->total_index_sectors - 1;
                        return AHFS_RES_OK;
                    }
                    /* 也不存在,提示需格式化文件系统 */
                    else
                    {
                        return AHFS_RES_ERR_FS;
                    }
                }
                else
                {
                    return AHFS_RES_ERR_RW;
                }
            }
        }
        else
        {
            /* 5 读取元数据和索引失败,返回失败 */
            return AHFS_RES_ERR_RW;
        }
    }
}

/*!
    @brief:     文件系统格式化
    @param[in]: fs 文件系统结构体指针
    @param[in]: format_mode 格式化方式
                0:格式化为物理扇区地址
                1:格式化为逻辑扇区地址+1（除0外所有参数）
    @param[out]:none
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
                AHFS_RES_ERR_FS 文件系统错误
*/
int8_t ahfs_format(ahfs_t *fs, uint8_t format_mode)
{
    int8_t ret = 0;
    if (fs == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }
    else
    {
        /* 0 读取标准时间戳 */
        uint32_t timestamp = fs->ahfs_get_current_timestamp();

        /* 1 初始化元数据 */
        fs->metadata.magic_number = MAGIC_NUMBER;
        fs->metadata.version = AHFS_VERSION;                                         // 版本号,eg:0x0103 表示1.3版本
        fs->metadata.sector_size = AHFS_SECTOR_SIZE;                                 // 扇区大小,单位：字节
        fs->metadata.total_sectors = AHFS_TOTAL_SECTORS;                             // 扇区总数,单位：扇区
        fs->metadata.max_indexes = AHFS_MAX_INDEXEX;                                 // 索引总数,单位：索引
        fs->metadata.physical_metadata_sector = AHFS_PHYSICAL_METADATA_SECTOR;       // 元数据所在物理扇区,通常为0
        fs->metadata.physical_index_start_sector = AHFS_PHYSICAL_INDEX_START_SECTOR; // 物理索引区起始扇区,通常为1
        uint32_t indexes_per_sector = fs->metadata.sector_size / sizeof(struct ahfs_index);
        uint32_t index_sectors = (fs->metadata.max_indexes + indexes_per_sector - 1) / indexes_per_sector; // 向上取整,避免不能整除时少一个扇区
        fs->metadata.physical_data_start_sector = fs->metadata.physical_index_start_sector + index_sectors;          // 物理数据区起始扇区
        if (format_mode == 0)
        {
            fs->metadata.logical_index_start_sector = fs->metadata.physical_index_start_sector; // 逻辑索引区起始扇区,环形
            fs->metadata.logical_data_start_sector = fs->metadata.physical_data_start_sector;   // 逻辑数据区起始扇区,环形
        }
        else
        {
            uint32_t sector = 0;
            uint16_t pos = 0;
            get_ring_index_location(fs, fs->indexes_per_sector, &sector, &pos); // 1个扇区
            fs->metadata.logical_index_start_sector = sector;
            get_ring_data_sector(fs, 
                                 fs->metadata.current_data_sector + 1 -fs->metadata.logical_data_start_sector,
                                 &sector); // 从当前扇区再+1个扇区
            fs->metadata.logical_data_start_sector = sector;
        }
        fs->metadata.active_index_count = 1;                                                                         // 已激活索引数量（<=max_indexes）,从1开始,并达到最大值后不再增加保持为最大值
        fs->metadata.current_index_id = 0;                                                                           // 当前操作的索引编号（持续递增,可能超过max_indexex）
        fs->metadata.current_data_sector = fs->metadata.logical_data_start_sector;                                   // 当前操作的数据扇区,始终是整扇区    写数据后也要更新
        fs->metadata.used_data_sectors = 0;                                                                          // 已使用的数据扇区数量,从0开始
        fs->metadata.crc16 = fs->ahfs_calculate_CRC16((uint8_t *)&(fs->metadata), sizeof(struct ahfs_metadata) - 2); // CRC16校验值,对除crc16外的所有字段进行校验

        /* 2 初始化索引 */
        fs->current_index.index_id = 0;                                         // 索引编号,从0开始,并且不会清零,=metadata.current_index_id
        fs->current_index.timestamp = timestamp;                                // 时间戳 支持到2037年
        fs->current_index.data_start_sector = fs->metadata.current_data_sector; // 本索引的数据区开始扇区号
        fs->current_index.data_bytes = 0;                                       // 数据长度(单位：字节)     写数据后也要更新

        /* 3 计算预计算参数 */
        fs->indexes_per_sector = fs->metadata.sector_size / sizeof(struct ahfs_index);
        fs->total_index_sectors = (fs->metadata.max_indexes + fs->indexes_per_sector - 1) / fs->indexes_per_sector; // 索引区扇区总数,利用向上取整技巧
        fs->total_data_sectors = fs->metadata.total_sectors - fs->total_index_sectors - 1;

        /* 4 写入元数据和索引到flash */
        if (fs->ahfs_write_metadata_index_to_flash(&(fs->metadata), &(fs->current_index)))
        {
            ret = AHFS_RES_ERR_RW;
        }

        /* 5 写入元数据和索引到存储器 */
        // 清空索引区所有扇区
        memset(fs->buf, 0, AHFS_SECTOR_SIZE);
        for (uint32_t i = 0; i < fs->total_index_sectors; i++)
        {
            if (disk_write(0, fs->buf, fs->metadata.physical_index_start_sector + i, 1))
            {
                ret = AHFS_RES_ERR_RW;
            }
        }
        // 把格式化后的第一组索引写到索引区,元数据写入元数据区
        if (write_metadata_index_to_storage(fs))
        {
            ret = AHFS_RES_ERR_RW;
        }

        return ret;
    }
}

/*!
    @brief:     计算存储器空间
    @param[out]:total_data_space 数据区总的空间（字节）
    @param[out]:free_data_space 数据区剩余可用空间（字节）
    @param[out]:total_index_count 索引区总的索引数
    @param[out]:free_index_count 索引区剩余可用索引数
    @retval:
*/
int8_t ahfs_get_storage_space(ahfs_t *fs,
                              uint64_t *total_data_space, uint64_t *free_data_space,
                              uint32_t *total_index_count, uint32_t *free_index_count)
{
    if (fs == NULL ||
        total_data_space == NULL || free_data_space == NULL ||
        total_index_count == NULL || free_index_count == NULL)
    {
        return AHFS_RES_ERR_PTR; // 传入的指针为空,返回错误
    }

    /* 计算索引区总的索引数和剩余可用索引数 */
    *total_index_count = fs->metadata.max_indexes;
    *free_index_count = fs->metadata.max_indexes - fs->metadata.active_index_count;

    /* 计算数据区总的空间和剩余可用空间 */
    *total_data_space = (uint64_t)(fs->total_data_sectors) * (uint64_t)AHFS_SECTOR_SIZE;
    uint64_t used_data_space = (uint64_t)fs->metadata.used_data_sectors * (uint64_t)AHFS_SECTOR_SIZE;
    uint8_t used_data_nofull_space = fs->current_index.data_bytes % AHFS_SECTOR_SIZE;

    // 计算数据区剩余可用空间
    *free_data_space = *total_data_space - used_data_space - used_data_nofull_space;

    return 0;
}

/*!
    @brief:     创建文件
    @param[in]: fs 文件系统结构体指针
    @param[out]:fs 文件系统结构体指针
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
                AHFS_RES_ERR_SPACE 索引区空间不足
*/
int8_t ahfs_create_file(ahfs_t *fs)
{
    int8_t ret = AHFS_RES_OK;
    if (fs == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }

    /* 1 检查索引区是否有足够空间 */
    if (fs->metadata.active_index_count >= fs->metadata.max_indexes)
    {
        return AHFS_RES_ERR_SPACE;
    }

    /* 2 读取标准时间戳 */
    uint32_t timestamp = fs->ahfs_get_current_timestamp();

    /* 3 更新索引 */
    // 计算要上一个文件占用的扇区数
    uint32_t last_file_sectors = (fs->current_index.data_bytes + fs->metadata.sector_size - 1) /
                                 fs->metadata.sector_size;
    int32_t sector_offset = fs->current_index.data_start_sector -
                            fs->metadata.logical_data_start_sector +
                            last_file_sectors;
    uint32_t sector = 0;
    uint8_t last_file_has_no_complete_sector = 0;
    get_ring_data_sector(fs, sector_offset, &sector);
    if (fs->current_index.data_bytes % fs->metadata.sector_size != 0)
    {
        last_file_has_no_complete_sector = 1; // 上一个文件有不完整的扇区 
    }

    fs->current_index.index_id += 1;
    fs->current_index.timestamp = timestamp;
    fs->current_index.data_start_sector = sector;
    fs->current_index.data_bytes = 0;

    /* 4 更新元数据 */
    if (fs->metadata.active_index_count < fs->metadata.max_indexes)
    {
        fs->metadata.active_index_count += 1;
    }
    fs->metadata.current_index_id = fs->current_index.index_id;
    fs->metadata.current_data_sector = fs->current_index.data_start_sector;
    fs->metadata.used_data_sectors += last_file_has_no_complete_sector; // 上一个文件有不完整的扇区,则used_data_sectors+1,这个扇区不再使用，因此可以认为已经使用
    fs->metadata.crc16 = fs->ahfs_calculate_CRC16((uint8_t *)&(fs->metadata), sizeof(struct ahfs_metadata) - 2); // CRC16校验值,对除crc16外的所有字段进行校验

    /* 5 写入元数据和索引到flash */
    if (fs->ahfs_write_metadata_index_to_flash(&(fs->metadata), &(fs->current_index)))
    {
        ret = AHFS_RES_ERR_RW;
    }

    /* 6 写入元数据和索引到存储器 */
    if (write_metadata_index_to_storage(fs))
    {
        ret = AHFS_RES_ERR_RW;
    }

    return ret;
}

/*!
    @brief:     写文件
    @param[in]: fs 文件系统结构体指针
    @param[in]: buf 要写入的数据
    @param[in]: size 要写入的数据长度
    @param[out]:none
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
                AHFS_RES_ERR_SPACE 空间不足
*/
int8_t ahfs_write_file(ahfs_t *fs, uint8_t *buf, uint32_t size)
{
    int8_t ret = AHFS_RES_OK;
    if (fs == NULL || buf == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }

    /* 1 计算本次写入后是否会超过 UINT32_MAX 因为fs->current_index.data_bytes是uint32_t类型 */
    if (size > UINT32_MAX - fs->current_index.data_bytes)
    {
        // 会溢出,创建新的 index,若创建失败则返回错误码
        if (ahfs_create_file(fs))
        {
            return AHFS_RES_ERR_SPACE;
        }
    }

    /* 2 检查数据区是否有足够空间,不够直接返回错误码 */
    uint64_t data_total = 0;
    uint64_t data_free = 0;
    uint32_t index_total = 0;
    uint32_t index_free = 0;
    ahfs_get_storage_space(fs, &data_total, &data_free, &index_total, &index_free);
    if (data_free < size)
    {
        return AHFS_RES_ERR_SPACE;
    }

    /* 3 计算当前扇区内的剩余空间 */
    uint16_t current_sector_offset = fs->current_index.data_bytes % AHFS_SECTOR_SIZE;
    uint16_t remaining_space = AHFS_SECTOR_SIZE - current_sector_offset;
    uint32_t written_remaining_bytes = 0;
    uint32_t written_remaining_sectors = 0;
    // 优先填充当前扇区的剩余空间
    if (remaining_space > 0 && remaining_space < AHFS_SECTOR_SIZE && size > 0)
    {
        uint32_t write_size = (size < remaining_space) ? size : remaining_space;
        if (disk_read(0, fs->buf, fs->metadata.current_data_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }
        memcpy(fs->buf + current_sector_offset, buf, write_size);
        if (disk_write(0, fs->buf, fs->metadata.current_data_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }
        written_remaining_bytes = write_size;

        // size 变化
        size -= write_size;

        if (write_size == remaining_space)
        {
            // 如果正好占满空间，则扇区需要加1
            written_remaining_sectors = 1;
        }
    }

    /* 4 从完整的扇区开始，计算要写入的扇区数 size已变化 */
    uint32_t sectors = size / AHFS_SECTOR_SIZE;
    uint16_t offset = size % AHFS_SECTOR_SIZE;
    if (size != 0)
    {
        uint32_t written_sectors = 0; // 记录已经写入的扇区数量
        // 处理完整扇区
        if (sectors > 0)
        {
            uint32_t current_sector = 0;
            get_ring_data_sector(fs,
                                 fs->metadata.current_data_sector -
                                     fs->metadata.logical_data_start_sector +
                                     written_remaining_sectors,
                                 &current_sector);
            uint32_t consecutive_sectors = 1;
            for (uint32_t i = 1; i < sectors; i++)
            {
                uint32_t next_sector = 0;
                get_ring_data_sector(fs,
                                     fs->metadata.current_data_sector -
                                         fs->metadata.logical_data_start_sector +
                                         written_remaining_sectors + 
                                         i,
                                     &next_sector);
                if (next_sector == current_sector + consecutive_sectors)
                {
                    // 如果下一个扇区是连续的,增加连续扇区数量
                    consecutive_sectors++;
                }
                else
                {
                    // 检查是否会越界
                    if (written_sectors * AHFS_SECTOR_SIZE + consecutive_sectors * AHFS_SECTOR_SIZE > size)
                    {
                        return AHFS_RES_ERR_OVERFLOW; // 越界错误
                    }
                    // 不连续则写入当前连续的扇区
                    if (disk_write(0, buf + written_remaining_bytes + written_sectors * AHFS_SECTOR_SIZE,
                                   current_sector, consecutive_sectors))
                    {
                        return AHFS_RES_ERR_RW;
                    }
                    // 重置连续扇区信息
                    written_sectors += consecutive_sectors;
                    current_sector = next_sector;
                    consecutive_sectors = 1;
                }
            }
            // 写入最后一组连续扇区
            // 检查最后一组连续扇区是否会越界
            if (written_sectors * AHFS_SECTOR_SIZE + consecutive_sectors * AHFS_SECTOR_SIZE > size)
            {
                return AHFS_RES_ERR_OVERFLOW; // 越界错误
            }
            if (disk_write(0, buf + written_remaining_bytes + written_sectors * AHFS_SECTOR_SIZE,
                           current_sector, consecutive_sectors))
            {
                return AHFS_RES_ERR_RW;
            }
            written_sectors += consecutive_sectors;
        }
        // 处理不完整扇区
        if (offset > 0)
        {
            uint32_t current_sector = 0;
            get_ring_data_sector(fs,
                                 fs->metadata.current_data_sector -
                                     fs->metadata.logical_data_start_sector +
                                     written_remaining_sectors +
                                     sectors,
                                 &current_sector);
            if (disk_read(0, fs->buf, current_sector, 1))
            {
                return AHFS_RES_ERR_RW;
            }
            memcpy(fs->buf, buf + written_remaining_bytes + written_sectors * AHFS_SECTOR_SIZE, offset);
            if (disk_write(0, fs->buf, current_sector, 1))
            {
                return AHFS_RES_ERR_RW; 
            }
        }
    }

    /* 5 更新当前索引的数据长度 */
    fs->current_index.data_bytes += written_remaining_bytes + size;

    /* 6 更新元数据的当前数据扇区 */
    uint32_t new_sector_offset = written_remaining_sectors + sectors;
    fs->metadata.used_data_sectors += new_sector_offset;
    uint32_t new_sector_physical = 0;
    get_ring_data_sector(fs,
                         fs->metadata.current_data_sector -
                             fs->metadata.logical_data_start_sector +
                             new_sector_offset,
                         &new_sector_physical);
    fs->metadata.current_data_sector = new_sector_physical;
    fs->metadata.crc16 = fs->ahfs_calculate_CRC16((uint8_t *)&(fs->metadata),
                                                  sizeof(struct ahfs_metadata) - 2); // CRC16校验值,对除crc16外的所有字段进行校验

    /* 7 写入元数据和索引到flash */
    if (fs->ahfs_write_metadata_index_to_flash(&(fs->metadata), &(fs->current_index)))
    {
        ret = AHFS_RES_ERR_RW;
    }

    /* 8 写入元数据和索引到存储器 */
    g_write_storage_counts++;
    if (g_write_storage_counts >= WRITE_COUNT_THRESHOLD_FOR_METADATA_INDEX_SYNC)
    {
        g_write_storage_counts = 0;
        if (write_metadata_index_to_storage(fs))
        {
            ret = AHFS_RES_ERR_RW;
        }
    }
    return ret;
}

/*!
    @brief:     同步文件系统
                因为在写文件的时候有均衡保护，在此强制刷新文件系统，将内存中的元数据和索引写入存储器
    @param[in]: fs 文件系统结构体指针
    @param[out]:none
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
*/
int8_t ahfs_sync(ahfs_t *fs)
{
    if (fs == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }
    /* 1 写入元数据和索引到存储器 */
    if (write_metadata_index_to_storage(fs))
    {
        return AHFS_RES_ERR_RW;
    }
    return AHFS_RES_OK;
}

/*!
    @brief:     计算要读取的所有文件的总字节数
    @param[in]: fs 文件系统结构体指针
    @param[in]: begin_index 开始索引
    @param[in]: end_index 结束索引
    @param[out]:size 要读取的数据长度
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
*/
int8_t ahfs_read_files_size(ahfs_t *fs,
                            uint32_t begin_index, uint32_t end_index,
                            uint32_t *files_size)
{
    if (fs == NULL || files_size == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }

    uint32_t read_len = 0;
    for (uint32_t i = begin_index; i < end_index + 1; i++)
    {
        uint32_t index_sector = 0;
        uint16_t index_offset = 0;
        get_ring_index_location(fs, i, &index_sector, &index_offset);
        if (disk_read(0, fs->buf, index_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }
        struct ahfs_index index = {0};
        index = *((struct ahfs_index *)fs->buf + index_offset);

        read_len += index.data_bytes;
    }
    *files_size = read_len;

    return AHFS_RES_OK;
}

/*!
    @brief:     读取指定索引范围的数据并通过上位机串口输出
                索引号可以通过 ahfs_read_files_list 获得
    @param[in]: begin_index 读取的起始索引
    @param[in]: end_index 读取的结束索引
    @param[out]:none
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_PTR 指针错误
                AHFS_RES_ERR_RW 读写错误
*/
int8_t ahfs_read_files_to_serial(ahfs_t *fs, uint32_t begin_index, uint32_t end_index)
{
    int8_t ret = AHFS_RES_OK;
    if (fs == NULL)
    {
        return AHFS_RES_ERR_PTR;
    }

    for (uint32_t i = begin_index; i < end_index + 1; i++)
    {
        uint32_t index_sector = 0;
        uint16_t index_offset = 0;
        get_ring_index_location(fs, i, &index_sector, &index_offset);
        if (disk_read(0, fs->buf, index_sector, 1))
        {
            return AHFS_RES_ERR_RW;
        }
        struct ahfs_index index = {0};
        index = *((struct ahfs_index *)fs->buf + index_offset);

        /* 1 读取索引对应的数据并通过串口发送出来 */
        uint32_t data_start_sector = index.data_start_sector;      
        uint32_t data_bytes = index.data_bytes;
        uint32_t data_sectors = data_bytes / AHFS_SECTOR_SIZE;
        uint16_t data_offset = data_bytes % AHFS_SECTOR_SIZE;
        uint32_t read_sector = 0;
        for (uint32_t j = 0; j < data_sectors; j++)
        {
            get_ring_data_sector(fs,
                                 data_start_sector - fs->metadata.logical_data_start_sector + j,
                                 &read_sector);
            if (disk_read(0, fs->buf, read_sector, 1))
            {
                return AHFS_RES_ERR_RW;
            }
            fs->ahfs_put_serial(fs->buf, AHFS_SECTOR_SIZE);
        }
        if (data_offset != 0)
        {
            get_ring_data_sector(fs,
                                 data_start_sector - fs->metadata.logical_data_start_sector + data_sectors,
                                 &read_sector);
            if (disk_read(0, fs->buf, read_sector, 1))
            {
                return AHFS_RES_ERR_RW;
            }
            fs->ahfs_put_serial(fs->buf, data_offset);
        }
    }
    return ret;
}

/*!
    @brief:     从存储器读取所有索引列表，并通过上位机串口输出。
                一定要注意在此前，将metadata和index写入sd，可通过以下操作：
                setmode 0,会调用 write_metadata_index_to_sd
                setmode 1,会调用 create_index 会调用 write_metadata_index_to_sd，
                          但是这个不行，mode1下不允许读取
                format, 会调用 deinit_index，
                          但是这个不行，因为就格式化了
    @param[in]: fs 文件系统结构体指针
    @param[out]:none
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_RW 读写错误
*/
int8_t ahfs_read_files_list_to_serial(ahfs_t *fs)
{
    for (uint32_t i = 0; i < fs->metadata.active_index_count; i++)
    {
        uint32_t index_sector = 0;
        uint16_t index_offset = 0;
        get_ring_index_location(fs, i, &index_sector, &index_offset);

        // 读取当前索引所在的扇区数据
        if (disk_read(0, fs->buf, index_sector, 1) != 0)
        {
            // 若读取失败，可根据需求添加错误处理逻辑，这里简单返回错误码
            return AHFS_RES_ERR_RW;
        }

        // 打印当前索引信息
        uint8_t put_buf[128] = {0};
        uint16_t put_len = fs->ahfs_generate_file_info_format(put_buf, (struct ahfs_index *)fs->buf + index_offset);
        fs->ahfs_put_serial(put_buf, put_len);
    }
    return AHFS_RES_OK;
}

/*!
    @brief:     写一个扇区数据
    @param[in]: sector 要写入的扇区
    @param[in]: buf 要写入的数据
    @param[out]:none
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_RW 读写错误
*/
int8_t ahfs_write_sector(uint32_t sector, uint8_t *buf)
{
    if (disk_write(0, buf, sector, 1))
    {
        return AHFS_RES_ERR_RW;
    }
    return AHFS_RES_OK;
}
/*!
    @brief:     读一个扇区数据
    @param[in]: sector 要读取的扇区
    @param[out]:buf 读取的数据
    @retval:    AHFS_RES_OK 成功
                AHFS_RES_ERR_RW 读写错误
*/
int8_t ahfs_read_sector(uint32_t sector, uint8_t *buf)
{
    if (disk_read(0, buf, sector, 1))
    {
        return AHFS_RES_ERR_RW;
    }
    return AHFS_RES_OK;
}
